package zxj.weixin.utils;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * XML工具类
 * 
 * @author zhuxuejiang
 *
 */
public class XmlUtils {

	private static final Logger LOGGER = LoggerFactory.getLogger(XmlUtils.class);

	/**
	 * 输入流转Map
	 * 
	 * @param input 输入流
	 * @return Map实体
	 * @throws DocumentException
	 */
	public static Map<String, Object> xml2Map(InputStream input) throws DocumentException {
		Map<String, Object> map = null;

		try {
			SAXReader saxReader = new SAXReader();
			Document document = saxReader.read(input);
			if (null == document) {
				return null;
			}

			Element root = document.getRootElement();
			if (null == root) {
				return null;
			}

			map = xml2Map(root);
		} catch (DocumentException e) {
			LOGGER.error("XML转Map错误！", e);
			throw e;
		}

		return map;
	}

	/**
	 * XML转Map
	 * 
	 * @param root XML根元素
	 * @return Map实体
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, Object> xml2Map(Element root) {
		if (null == root) {
			return null;
		}

		Map<String, Object> map = new HashMap<>(16);
		List<Element> elements = root.elements();
		for (Element element : elements) {
			if (element.elements().size() > 0) {
				map.put(element.getName(), xml2Map(element));
			} else {
				map.put(element.getName(), element.getText());
			}
		}

		return map;
	}

	/**
	 * Map转XML字符串
	 * 
	 * @param map Map实体
	 * @return XML字符串
	 */
	public static String map2XmlString(Map<String, Object> map) {
		Document document = DocumentHelper.createDocument();
		document.setXMLEncoding("UTF-8");
		Element root = document.addElement("xml");

		map2Xml(root, map);
		return root.asXML();
	}

	/**
	 * 将Map转换成XML，并添加到父元素下
	 * 
	 * @param parent XML父元素
	 * @param map    Map实体
	 */
	@SuppressWarnings("unchecked")
	public static void map2Xml(Element parent, Map<String, Object> map) {

		for (Entry<String, Object> entry : map.entrySet()) {
			Element element = parent.addElement(entry.getKey());

			if (entry.getValue() instanceof Map) {
				map2Xml(element, (Map<String, Object>) entry.getValue());
			} else if (entry.getValue() instanceof List) {
				list2Xml(element, (List<Object>) entry.getValue());
			} else {
				element.setText("" + entry.getValue());
			}
		}

	}

	/**
	 * 将List转换成XML，并添加到父元素下
	 * 
	 * @param parent XML父元素
	 * @param list   List实体
	 */
	@SuppressWarnings("unchecked")
	public static void list2Xml(Element parent, List<Object> list) {
		for (Object obj : list) {
			if (obj instanceof Map) {
				map2Xml(parent, (Map<String, Object>) obj);
			} else if (obj instanceof List) {
				list2Xml(parent, (List<Object>) obj);
			} else {
				parent.addElement("" + obj);
			}
		}

	}
}
